package ch.fusun.baron.map.ui.views;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.part.ViewPart;

import ch.fusun.baron.core.injection.Inject;
import ch.fusun.baron.core.injection.ReInjector;
import ch.fusun.baron.data.DataListener;
import ch.fusun.baron.data.DataUpdate;
import ch.fusun.baron.map.api.GameMapService;
import ch.fusun.baron.map.ui.Activator;
import ch.fusun.baron.map.ui.gef.editpart.TileChild;
import ch.fusun.baron.map.ui.gef.editpart.TileChildrenProvider;
import ch.fusun.baron.map.ui.gef.editpart.TileExtensionUtil;
import ch.fusun.baron.swt.isometry.SpriteSelectionListener;
import ch.fusun.baron.swt.isometry.components.IsometryWidget;
import ch.fusun.baron.swt.isometry.components.Sprite;
import ch.fusun.baron.turn.UserTurnService;

/**
 * Displays a map
 */
public class MapView extends ViewPart implements DataListener {

	private static final String ICONS_TILES_MASK = "icons/tiles/0_mask.png"; //$NON-NLS-1$

	private static final String ICONS_TILES = "icons/tiles/0.png"; //$NON-NLS-1$

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "ch.fusun.baron.map.ui.views.MapView"; //$NON-NLS-1$

	@Inject
	private GameMapService mapService;

	@Inject
	private UserTurnService turnService;

	private IsometryWidget isometryWidget;

	/**
	 * The constructor.
	 */
	public MapView() {
		ReInjector.getInstance().reInject(this);
	}

	@Override
	public void createPartControl(Composite parent) {
		parent.setLayout(new GridLayout());
		isometryWidget = new IsometryWidget(parent, SWT.NONE,
				mapService.getWidth(), mapService.getHeight(), 1, 64, 64, 32);
		isometryWidget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true));

		isometryWidget.addSelectionListener(new SpriteSelectionListener() {
			@Override
			public void itemSelected(IStructuredSelection iSelection) {
				handleNewSelection(iSelection);
			}
		});

		this.mapService.addDataListener(this);
		this.turnService.addDataListener(this);
		for (TileChildrenProvider provider : TileExtensionUtil.getInstance()
				.getProviders()) {
			provider.addListener(this);
		}
	}

	/**
	 * @param iSelection
	 *            the new selection
	 */
	protected void handleNewSelection(IStructuredSelection iSelection) {
		// ALG FIXME Solves this with listeners!!!
		IViewPart commandView = getSite().getWorkbenchWindow().getActivePage()
				.findView(CommandView.ID);
		if (commandView != null) {
			((CommandView) commandView).updateSelection(iSelection);
		}

		IViewPart selectionView = getSite().getWorkbenchWindow()
				.getActivePage().findView(SelectionView.ID);
		if (selectionView != null) {
			((SelectionView) selectionView).updateSelection(iSelection);
		}
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	@Override
	public void setFocus() {
		// Do nothing
	}

	@Override
	public void dataChanged(DataUpdate update) {
		final Display display = getSite().getShell().getDisplay();
		display.asyncExec(new Runnable() {
			@Override
			public void run() {
				handleDataChange();
			}
		});
	}

	/**
	 * The data changed
	 */
	protected synchronized void handleDataChange() {
		IStructuredSelection selection = isometryWidget.getSelection();
		isometryWidget.setDimension(this.mapService.getWidth(),
				this.mapService.getHeight(), 1);
		isometryWidget.clear();
		for (int i = 0; i < this.mapService.getWidth(); i++) {
			for (int j = 0; j < this.mapService.getHeight(); j++) {
				isometryWidget.addItem(
						mapService.getTile(i, j),
						i,
						j,
						new Sprite(Activator.getImage(ICONS_TILES), Activator
								.getImage(ICONS_TILES_MASK)));
				for (TileChild<?> child : TileExtensionUtil.getInstance()
						.getChildren(mapService.getTile(i, j))) {
					isometryWidget.addItem(child.getModel(), i, j,
							child.getSprite());
				}
			}
		}
		this.isometryWidget.setSelection(selection);
		if (!this.isometryWidget.isDisposed()) {
			this.isometryWidget.redraw();
		}
	}

	/**
	 * Turns the map by 90�
	 */
	public void turn() {
		this.isometryWidget.turn();
	}

	/**
	 * Turns the map by 90� anti clockwise
	 */
	public void turnCounterClockWise() {
		this.isometryWidget.turnCounterClockWise();
	}

}